package com.maizhi.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;

import com.maizhi.model.Files;
 


public class FileUpload  {
	
//  config.properties
//	SaveBAKPath=/mzUploadBak
//	SavePath=/upload
//	allowFileTypes=image/jpeg,image/gif,image/pjpeg,image/png,image/bmp,text/plain,application/msword,application/vnd.ms-excel,application/octet-stream
//	cacheSavePath=/uploadFileCache
//	cacheSize=4096
//	excelPath=/excelFile
//	excelSize=50000
//	fileLimitSize=10M
//	onceMaxSize=-1
//	tempSavePath=/uploadFileTemp
	
	private static final Logger logger = Logger.getLogger(FileUpload.class);
   	public static ResourceBundle config = ResourceBundle.getBundle("config");
   	
   	
   	private String SavePath = config.getString("SavePath");
	private String SaveBAKPath = config.getString("SaveBAKPath");
	
	//设置上传文件最大值
	private long MAX_SIZE = 300 * 1024 * 1024;
	//默认的文件上传类型限制
    private String allowFileTypes = config.getString("allowFileTypes");
    
    public long getMAX_SIZE() {
		return MAX_SIZE;
	}

	public void setMAX_SIZE(long max_size) {
		MAX_SIZE = max_size;
	}
    
    private boolean isAllowFileType(String fileType)
    {
        if (allowFileTypes.length() > 0 && fileType.trim().length() > 0)
            return allowFileTypes.indexOf(fileType.toLowerCase()) != -1;
        else
            return true;
    }

    /**
     * @return [String] 允许上传的文件类型
     */
    public String getAllowFileTypes()
    {
        return allowFileTypes;
    }

    /**
     * 设置允许上传的文件类型，默认是""，无限制
     * 
     * @param allowFileTypes
     */
    public void setAllowFileTypes(String allowFileTypes)
    {
        this.allowFileTypes = allowFileTypes;
    }

    public void addAllowFileTypes(String allowFileTypes)
    {
        this.allowFileTypes += ("," + allowFileTypes);
    }
   
    public FileUpload()
	{	
    	int tmpIndex = SavePath.lastIndexOf("/");
    	String SaveFolderName=tmpIndex>=0?SavePath.substring(tmpIndex):SavePath;
    	FileCreate(SaveFolderName); 
    	
    	tmpIndex = SaveBAKPath.lastIndexOf("/");
    	SaveFolderName=tmpIndex>=0?SaveBAKPath.substring(tmpIndex):SaveBAKPath;
    	FileCreate(SaveFolderName);
	}
    
    public void FileCreate(String fileName){
    	File file = new File(fileName);
    	if(!file.exists()){
    		file.mkdir();
    	}
    }
 
    //下载文件
    public void downLoad(String filename,String oldFileName,HttpServletResponse response,boolean isOnLine) throws Exception
	{
    	String filePath = filename;
		
		File f = new File(filePath);
		
		if(!f.exists())
		{
			response.sendError(404,"File not found, fileName:"+filePath);
			return;
		}
		
		BufferedInputStream br = new BufferedInputStream(new FileInputStream(f));
		byte[] buf = new byte[1024];
		int len = 0;
		
		//String fileName = f.getName();
		String fileName = new String(oldFileName.getBytes("GBK"),"ISO8859_1");       
		
		
		response.reset(); //非常重要
		if(isOnLine)//在线打开方式
		{ 
			URL u = new URL("file:///"+filePath);
			response.setContentType("application/zip");
			if (u.openConnection().getContentType().equals("text/plain") ||
				u.openConnection().getContentType().equals("text/xml") ||
				u.openConnection().getContentType().equals("text/html"))
			{
				response.setContentType(u.openConnection().getContentType()+";charset=GB2312");
			}else response.setContentType(u.openConnection().getContentType()+";charset=UTF-8");
			//text/html
			 
			response.setHeader("Content-Disposition", "inline; filename="+fileName);
			//文件名应该编码成UTF-8
		}else
		{ 	//纯下载方式
			response.setContentType("application/x-msdownload"); 
			response.setHeader("Content-Disposition", "attachment; filename=" + fileName); 
		}	
		
		OutputStream out = response.getOutputStream();
		while((len = br.read(buf)) >0)
		out.write(buf,0,len);
		br.close();
		out.close();
	} 
    
   /**
    * 
    * @param request
    * @param response
    * @return [0]：原文件名[1]:系统生成文件名[2]:文件大小
    */
	public List<Files> uploadFilesArr(HttpServletRequest request, HttpServletResponse response)
	{
		List<Files> ReturnStr  = new Vector<Files>();
		response.setContentType("text/html");
		
		// 设置字符编码为UTF-8, 统一编码，处理出现乱码问题
		response.setCharacterEncoding("gbk");
		
		// 实例化一个硬盘文件工厂,用来配置上传组件ServletFileUpload
		DiskFileItemFactory dfif = new DiskFileItemFactory();
	
		dfif.setSizeThreshold(4096);// 设置上传文件时用于临时存放文件的内存大小,这里是4K.多于的部分将临时存在硬盘
		
		String dp = request.getRealPath("/")+SavePath;
		
		logger.debug("dp : "+dp);
		
		this.FileCreate(dp);
		
		dfif.setRepository(new File(dp));// 设置存放临时文件的目录,web根目录下的ImagesUploadTemp目录
		
		logger.debug("request.getRealPath('/')+SavePath : "+request.getRealPath("/")+SavePath);
		
		// 用以上工厂实例化上传组件
		ServletFileUpload sfu = new ServletFileUpload(dfif);
		
		logger.debug("sfu : "+sfu+" DiskFileItemFactory dfif : "+dfif);
		
		// 设置最大上传大小
		sfu.setSizeMax(MAX_SIZE); 
		
		//PrintWriter out = response.getWriter();
		// 从request得到所有上传域的列表
		List fileList = null;
	
		PrintWriter printwriter=null;
		try
		{
			printwriter = response.getWriter();
		}catch (Exception e) 
		{
           logger.error("checkLogin err");
		}
		
		try {
			fileList = sfu.parseRequest(request);
			
			logger.debug("fileList : "+fileList+ "fileList.size() : "+fileList.size());
			
			//没有选择文件
			if (fileList != null && fileList.size() >0) 
			{
				int file_i=0;
				Iterator fileItr = fileList.iterator();
				
				//循环处理所有文件
				while (fileItr.hasNext())
				{
					String strArr[] = null;
					strArr = new String[]{"","","",""};
					FileItem fileItem = null;
					String path = null;
					long size = 0;
				
					// 得到当前文件
					fileItem = (FileItem) fileItr.next();
					// 忽略简单form字段而不是上传域的文件域(<input type="text" />等)
					if (fileItem == null || fileItem.isFormField()) 
					{
						continue;
					}
					// 得到文件的完整路径
					path = fileItem.getName();
					// 得到文件的大小
					size = fileItem.getSize();
				
					logger.debug("size : "+size);
					
					if ("".equals(path)==false && size > 0) 
					{
						strArr[2] = String.valueOf(size);
						
						//得到去除路径的文件名
						String t_name = path.substring(path.lastIndexOf("\\") + 1);
						if(t_name.indexOf("*")>0 || t_name.indexOf("!")>0) {printwriter.print("<script>alert('文件名中包含非法字符！');</script>"); continue;} //文件名中不能包含分号
						//得到文件的扩展名(无扩展名时将得到全名)
						String t_ext = t_name.substring(t_name.lastIndexOf(".") + 1);
						strArr[0] = t_name.replaceAll(" ", "");
						// 拒绝接受规定文件格式之外的文件类型
						 String fileContentType = fileItem.getContentType();
						  if (isAllowFileType(fileContentType)) // 不属于允许上传的文件类型
                          {
							  	long now = System.currentTimeMillis();
								// 根据系统时间生成上传后保存的文件名
								String prefix = String.valueOf(now);
								// 保存的最终文件完整路径,保存在web根目录下的ImagesUploaded目录下
								String u_name = request.getRealPath("/") + SavePath+"\\"
								+ prefix + "." + t_ext;
								//String filename = prefix + "." + t_ext;
								//根据新文件名保存文件
								String filename=prefix + "." + t_ext;
								strArr[1] = filename;
								
								
							try {
						
									fileItem.write(new File(u_name));
									//备份
									FileInputStream   fis   =   new   FileInputStream(u_name); 
					         		String DstFileName = SaveBAKPath +"/"+filename;
					         		FileOutputStream   fos  =  new   FileOutputStream(DstFileName); 
									byte[]   buff   =   new byte[1024]; 
									int   readed   =   -1; 
							
									while((readed   =   fis.read(buff))   >   0) 
									{	
										fos.write(buff,   0,   readed);
									}
								
									fis.close(); 
									fos.close();
									
									 Files files = new Files();
									 
									 files.setCreateDate(new Date());
									 files.setFileName(t_name.trim());
									 files.setFilePath(filename);
									 files.setFileSubffix(t_ext);
									 files.setFileStatus(1);
									 files.setFileSize(size); 
									 
									 ReturnStr.add(files);
									 
								} catch (Exception e)
								{ 
									logger.error(e.getLocalizedMessage());
									printwriter.print("<script>alert('"+e.getLocalizedMessage()+"！');</script>");
									continue;
								}
								
								
                          }else {
                        	  logger.debug("不属于允许上传的文件类型");
                        	  printwriter.print("<script>alert('不属于允许上传的文件类型！');</script>"); return null;};
						 
					} else {
						logger.debug("文件路径错误");
						printwriter.print("<script>alert('文件路径错误！');</script>"); return null;};
					
					
				}
			}
		} catch (FileUploadException e)
		{// 处理文件尺寸过大异常
			ReturnStr = null;
			if (e instanceof SizeLimitExceededException)
			{	
				//System.out.println("文件尺寸超过规定大小:" + MAX_SIZE + "字节<p />");
				logger.debug("文件尺寸超过规定大小:" + MAX_SIZE + "字节<p />！");
				printwriter.print("<script>alert('文件尺寸超过规定大小:" + MAX_SIZE + "字节<p />！');</script>");
				return null;
				
			}
	
			logger.error("2222222222222222"+e.getLocalizedMessage());
			printwriter.print("<script>alert('"+e.getLocalizedMessage()+"！');</script>");
			return null;
		}
		
		return ReturnStr;
	}
	
	
	   /**
	    * 
	    * @param request
	    * @param response
	    * @return [0]：原文件名[1]:系统生成文件名[2]:文件大小
	    */
		public List<Files> uploadFilesArr(HttpServletRequest request, HttpServletResponse response,String saveFileName)
		{
			List<Files> ReturnStr  = new Vector<Files>();
			
			response.setContentType("text/html");
			
			// 设置字符编码为UTF-8, 统一编码，处理出现乱码问题
			response.setCharacterEncoding("gbk");
			
			// 实例化一个硬盘文件工厂,用来配置上传组件ServletFileUpload
			DiskFileItemFactory dfif = new DiskFileItemFactory();
		
			dfif.setSizeThreshold(4096);// 设置上传文件时用于临时存放文件的内存大小,这里是4K.多于的部分将临时存在硬盘
			
			dfif.setRepository(new File(request.getRealPath("/")+SavePath));// 设置存放临时文件的目录,web根目录下的ImagesUploadTemp目录
			
			// 用以上工厂实例化上传组件
			ServletFileUpload sfu = new ServletFileUpload(dfif);
			// 设置最大上传大小
			sfu.setSizeMax(MAX_SIZE); 
			
			//PrintWriter out = response.getWriter();
			// 从request得到所有上传域的列表
			List fileList = null;
		
			PrintWriter printwriter=null;
			try
			{
				printwriter = response.getWriter();
			}catch (Exception e) 
			{
	           logger.error("checkLogin err");
			}
			
			try {
				
			
				
				fileList = sfu.parseRequest(request);
				
				//没有选择文件
				if (fileList != null && fileList.size() >0) 
				{
					
					int file_i=0;
					Iterator fileItr = fileList.iterator();
					
					
//					 循环处理所有文件
					while (fileItr.hasNext())
					{
						String strArr[] = null;
						strArr = new String[]{"","","",""};
						FileItem fileItem = null;
						String path = null;
						long size = 0;
					
						// 得到当前文件
						fileItem = (FileItem) fileItr.next();
						// 忽略简单form字段而不是上传域的文件域(<input type="text" />等)
						if (fileItem == null || fileItem.isFormField()) 
						{
							continue;
						}
						// 得到文件的完整路径
						path = fileItem.getName();
						// 得到文件的大小
						size = fileItem.getSize();
					
						
						if ("".equals(path)==false && size > 0) 
						{
							strArr[2] = String.valueOf(size);
							
							//	 得到去除路径的文件名
							String t_name = path.substring(path.lastIndexOf("\\") + 1);
							if(t_name.indexOf("*")>0 || t_name.indexOf("!")>0) {printwriter.print("<script>alert('文件名中包含非法字符！');</script>"); continue;} //文件名中不能包含分号
//							 得到文件的扩展名(无扩展名时将得到全名)
							String t_ext = t_name.substring(t_name.lastIndexOf(".") + 1);
							strArr[0] = t_name.replaceAll(" ", "");
							// 拒绝接受规定文件格式之外的文件类型
							 String fileContentType = fileItem.getContentType();
							  if (isAllowFileType(fileContentType)) // 不属于允许上传的文件类型
	                          {
								  	//long now = System.currentTimeMillis();
									// 根据系统时间生成上传后保存的文件名
									String prefix = saveFileName;
									// 保存的最终文件完整路径,保存在web根目录下的ImagesUploaded目录下
									String u_name = request.getRealPath("/") + SavePath+"\\"
									+ prefix + "." + t_ext;
									//String filename = prefix + "." + t_ext;
									//根据新文件名保存文件
									String filename=prefix + "." + t_ext;
									strArr[1] = filename;
									
									
								try {
							
										fileItem.write(new File(u_name));
								
										//备份
										FileInputStream   fis   =   new   FileInputStream(u_name); 
						         		String DstFileName = SaveBAKPath +"/"+filename;
						         		FileOutputStream   fos  =  new   FileOutputStream(DstFileName); 
										byte[]   buff   =   new byte[1024]; 
										int   readed   =   -1; 
								
										while((readed   =   fis.read(buff))   >   0) 
										{	
											fos.write(buff,   0,   readed);
										}
									
										fis.close(); 
										fos.close();
										
										Files files = new Files();
										 
									    files.setCreateDate(new Date());
										files.setFileName(t_name.trim());
										files.setFilePath(filename);
										files.setFileSubffix(t_ext);
										files.setFileStatus(1);
										files.setFileSize(size); 
										 
										ReturnStr.add(files);
 
									} catch (Exception e)
									{ 
										printwriter.print("<script>alert('"+e.getLocalizedMessage()+"！');</script>");
										continue;
									}
									
									
	                          }else {printwriter.print("<script>alert('不属于允许上传的文件类型！');</script>"); return null;};
							 
						} else {printwriter.print("<script>alert('文件路径错误！');</script>"); return null;};
						
						
					}
				}
			} catch (FileUploadException e)
			{// 处理文件尺寸过大异常
				ReturnStr = null;
				if (e instanceof SizeLimitExceededException)
				{	
					//System.out.println("文件尺寸超过规定大小:" + MAX_SIZE + "字节<p />");
					printwriter.print("<script>alert('文件尺寸超过规定大小:" + MAX_SIZE + "字节<p />！');</script>");
					return null;
					
				}
		
				printwriter.print("<script>alert('"+e.getLocalizedMessage()+"！');</script>");
				return null;
			}
			
			return ReturnStr;
		}
		

	
	
	
}

